package cn.trigram.mgb.api.java;

import static org.mybatis.generator.internal.util.StringUtility.isTrue;

import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.Set;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;

public class CommonCommentGenerator extends DefaultCommentGenerator {

  protected final Properties properties = new Properties();

  protected boolean suppressDate;

  protected boolean suppressAllComments;

  /**
   * If suppressAllComments is true, this option is ignored.
   */
  protected boolean addRemarkComments;

  protected SimpleDateFormat dateFormat;

  @Override
  public void addConfigurationProperties(Properties props) {

    this.properties.putAll(props);

    suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));

    suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));

    addRemarkComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));

    String dateFormatString = properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_DATE_FORMAT);
    if (StringUtility.stringHasValue(dateFormatString)) {
      dateFormat = new SimpleDateFormat(dateFormatString);
    }
  }

  @Override
  public void addGeneralMethodAnnotation(
      Method method, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports
  ) {

    imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); //$NON-NLS-1$
    String generatedComment = String.format(
        "@Generated(comments = \"Source Table: %s\", value = {})",
        introspectedTable.getFullyQualifiedTable().toString()
    );
    method.addAnnotation(generatedComment);
  }

  @Override
  public void addGeneralMethodAnnotation(
      Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn,
      Set<FullyQualifiedJavaType> imports
  ) {

    imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); //$NON-NLS-1$
    String generatedComment = String.format(
        "@Generated(comments = \"Source field: %s.%s\", value = {})",
        introspectedTable.getFullyQualifiedTable().toString(), introspectedColumn.getActualColumnName()
    );
    method.addAnnotation(generatedComment);
  }

  @Override
  public void addFieldAnnotation(
      Field field, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports
  ) {

    imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); //$NON-NLS-1$
    String generatedComment = String.format(
        "@Generated(comments = \"Source Table: %s\", value = {})",
        introspectedTable.getFullyQualifiedTable().toString()
    );
    field.addAnnotation(generatedComment);
  }

  @Override
  public void addFieldAnnotation(
      Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn,
      Set<FullyQualifiedJavaType> imports
  ) {

    imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); //$NON-NLS-1$
    String generatedComment = String.format(
        "@Generated(comments = \"Source field: %s.%s\", value = {})",
        introspectedTable.getFullyQualifiedTable().toString(), introspectedColumn.getActualColumnName()
    );
    field.addAnnotation(generatedComment);
  }

  @Override
  public void addClassAnnotation(
      InnerClass innerClass, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports
  ) {

    imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); //$NON-NLS-1$
    String generatedComment = String.format(
        "@Generated(comments = \"Source Table: %s\", value = {})",
        introspectedTable.getFullyQualifiedTable().toString()
    );
    innerClass.addAnnotation(generatedComment);
  }

  @Override
  public void addFieldComment(
      Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn
  ) {

    if (suppressAllComments) {
      return;
    }

    field.addJavaDocLine("/**"); //$NON-NLS-1$

    String remarks = introspectedColumn.getRemarks();
    if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
      field.addJavaDocLine(" * Column:" + introspectedColumn.getActualColumnName()); //$NON-NLS-1$
      field.addJavaDocLine(" * <br/>"); //$NON-NLS-1$
      String[] remarkLines = remarks.split(System.getProperty("line.separator")); //$NON-NLS-1$
      for (String remarkLine : remarkLines) {
        field.addJavaDocLine(" * " + remarkLine); //$NON-NLS-1$
      }
    }

    field.addJavaDocLine(" */"); //$NON-NLS-1$
  }

  @Override
  public void addFieldComment(Field field, IntrospectedTable introspectedTable) {

    if (suppressAllComments) {
      return;
    }

    field.addJavaDocLine("/**"); //$NON-NLS-1$
    field.addJavaDocLine(" * 请补充注释"); //$NON-NLS-1$
    field.addJavaDocLine(" */"); //$NON-NLS-1$
  }

  @Override
  public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {

    if (suppressAllComments) {
      return;
    }

    method.addJavaDocLine("/**"); //$NON-NLS-1$
    method.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable() + "表的基本CRUD");
    method.addJavaDocLine(" */"); //$NON-NLS-1$
  }

  @Override
  public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

    if (suppressAllComments || !addRemarkComments) {
      return;
    }

    topLevelClass.addJavaDocLine("/**"); //$NON-NLS-1$
    topLevelClass.addJavaDocLine(
        " * " + introspectedTable.getFullyQualifiedTable() + "表的数据模型类"); //$NON-NLS-1$
    topLevelClass.addJavaDocLine(" * <br/>"); //$NON-NLS-1$
    String remarks = introspectedTable.getRemarks();
    if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
      String[] remarkLines = remarks.split(System.getProperty("line.separator")); //$NON-NLS-1$
      for (String remarkLine : remarkLines) {
        topLevelClass.addJavaDocLine(" * " + remarkLine); //$NON-NLS-1$
      }
    }
    topLevelClass.addJavaDocLine(" */"); //$NON-NLS-1$
  }

  @Override
  public void addComment(XmlElement xmlElement) {

    if (suppressAllComments) {
      return;
    }
    if ("select".equals(xmlElement.getName())) {
      xmlElement.addElement(new TextElement("<!--@formatter:off-->")); //$NON-NLS-1$
        }
    }
}
